package cn.achao.csr.zfb.service.imp;

import cn.achao.csr.api.AuthApi;
import cn.achao.csr.api.SysUserApi;
import cn.achao.csr.api.model.dto.ZfbNotifyDTO;
import cn.achao.csr.api.model.dto.ZfbRegisterDTO;
import cn.achao.csr.api.model.resp.AliUserInfoResp;
import cn.achao.csr.base.constant.enums.SysSourceEnum;
import cn.achao.csr.base.exception.BusinessException;
import cn.achao.csr.base.resp.R;
import cn.achao.csr.base.utils.StringUtils;
import cn.achao.csr.base.utils.ThrowUtils;
import cn.achao.csr.zfb.service.AliLoginService;
import com.alibaba.fastjson2.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.request.AlipayUserInfoShareRequest;
import com.alipay.api.response.AlipayUserInfoShareResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import static cn.achao.csr.base.constant.AliConstants.*;

/**
 * @Author: achao
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class AliLoginServiceImpl implements AliLoginService {

    private final AlipayClient alipayClient;
    private final SysUserApi sysUserApi;
    private final AuthApi authApi;

    @Override
    public AliUserInfoResp.AlipayUserInfoShareResponseDTO getUserInfo(String authCode) {
        // 获取token
        AlipaySystemOauthTokenRequest tokenRequest = new AlipaySystemOauthTokenRequest();
        tokenRequest.setCode(authCode);
        tokenRequest.setGrantType(AUTHORIZATION_CODE);

        try {
            // 使用auth_code换取支付宝的token
            String token = alipayClient.execute(tokenRequest).getAccessToken();

            // 使用token获取支付宝用户信息
            AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest();
            AlipayUserInfoShareResponse resp = alipayClient.execute(request, token);
            ThrowUtils.throwIf(!resp.isSuccess(),
                    BusinessException.fail("获取用户信息失败", SysSourceEnum.CSR_ZFB.getSysName()));
            AliUserInfoResp.AlipayUserInfoShareResponseDTO zfUserInfo = getZfUserInfo(resp);
            log.info("支付宝用户信息：{}", JSON.toJSONString(zfUserInfo));
            return zfUserInfo;
        } catch (AlipayApiException e) {
            log.error("getUserInfo 获取支付宝用户信息异常：{}", e.getMessage());
            ThrowUtils.throwIf(BusinessException.fail("获取支付宝用户信息异常", SysSourceEnum.CSR_ZFB.getSysName()));
        }
        return null;
    }

    @Override
    public R<?> notifyAuth(AliUserInfoResp.AlipayUserInfoShareResponseDTO userInfo, String state) {
        return authApi.zfbNotify(buildZfbNotifyDTOByUserInfo(userInfo, state));
    }

    /**
     * 构建支付宝回调的DTO
     *
     * @param userInfo
     * @param state
     * @return
     */
    private ZfbNotifyDTO buildZfbNotifyDTOByUserInfo(AliUserInfoResp.AlipayUserInfoShareResponseDTO userInfo, String state) {
        ThrowUtils.throwIf(StringUtils.isBlank(state),
                BusinessException.fail("支付宝回调参数异常", SysSourceEnum.CSR_ZFB.getSysName()));
        String status = state.substring(0, 1);
        String account = "";
        if (state.length() > 1) {
            account = state.substring(1);
        }
        ZfbNotifyDTO zfbNotifyDTO = ZfbNotifyDTO.builder()
                .status(status)
                .userAccount(account)
                .registerInfo(ZfbRegisterDTO.builder()
                        .nickName(userInfo.getNick_name())
                        .zfbOpenId(StringUtils.isNotBlank(userInfo.getOpen_id()) ? userInfo.getOpen_id() : userInfo.getUser_id())
                        .zfbUserInfo(JSON.toJSONString(userInfo))
                        .build())
                .build();

        return zfbNotifyDTO;
    }

    /**
     * 获取支付宝的用户信息
     *
     * @param resp
     * @return
     */
    private AliUserInfoResp.AlipayUserInfoShareResponseDTO getZfUserInfo(AlipayUserInfoShareResponse resp) {
        try {
            String body = resp.getBody();
            AliUserInfoResp aliUserInfoResp = JSON.parseObject(body, AliUserInfoResp.class);
            AliUserInfoResp.AlipayUserInfoShareResponseDTO alipayUserInfo = aliUserInfoResp.getAlipay_user_info_share_response();
            ThrowUtils.throwIf(alipayUserInfo == null || (StringUtils.isAllBlank(alipayUserInfo.getUser_id(), alipayUserInfo.getOpen_id())),
                    BusinessException.fail("支付宝用户信息为空", SysSourceEnum.CSR_ZFB.getSysName()));
            return alipayUserInfo;
        } catch (Exception e) {
            log.error("getZfUserInfo 支付宝用户信息解析失败：{}", e.getMessage());
            ThrowUtils.throwIf(BusinessException.fail("支付宝用户信息解析失败", SysSourceEnum.CSR_ZFB.getSysName()));
        }
        return null;
    }
}
